//#define USE_DUNGEONBUDDY_DLL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using CommonBehaviors.Actions;
using Styx;
using Styx.Common.Helpers;
using Styx.CommonBot;
using Styx.CommonBot.Frames;
using Styx.Helpers;
using Styx.Patchables;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
#if USE_DUNGEONBUDDY_DLL
using Bots.DungeonBuddyDll;
using Bots.DungeonBuddyDll.Profiles;
using Bots.DungeonBuddyDll.Attributes;
using Bots.DungeonBuddyDll.Helpers;

namespace Bots.DungeonBuddyDll.Dungeon_Scripts.Mists_of_Pandaria
#else
    using Bots.DungeonBuddy.Profiles;
    using Bots.DungeonBuddy.Attributes;
    using Bots.DungeonBuddy.Helpers;
namespace Bots.DungeonBuddy.Dungeon_Scripts.Mists_of_Pandaria
#endif
{

    #region Normal Difficulty

    public class CryptOfForgottenKings : Dungeon
    {
        #region Overrides of Dungeon

        public override uint DungeonId
        {
            get { return 504; }
        }

        public override void RemoveTargetsFilter(List<WoWObject> units)
        {
            units.RemoveAll(
                ret =>
                    {
                        var unit = ret.ToUnit();
                        if (unit != null)
                        {
                            if (unit.Entry == CryptGuardianFuryId && (unit.CastingSpellId == BladestormId || unit.HasAura(BladestormId)) && Me.IsMelee())
                                return true;
                            if (unit.Entry == AbominationOfAngerId && unit.ChanneledCastingSpellId == DeathforceId && Me.IsMelee())
                                return true;
                        }
                        return false;
                    });
        }

        public override void IncludeTargetsFilter(List<WoWObject> incomingunits, HashSet<WoWObject> outgoingunits)
        {
            foreach (var obj in incomingunits)
            {
                var unit = obj as WoWUnit;
                if (unit != null)
                {
                    if (unit.Entry == JinIronfistId && Me.IsTank() && unit.Distance < 40)
                        outgoingunits.Add(unit);

                    // if (unit.Entry == ShadowsofAngerId && unit.Distance <= 40)
                    //      outgoingunits.Add(unit);

                }
            }
        }

        public override void WeighTargetsFilter(List<Targeting.TargetPriority> units)
        {
            foreach (var priority in units)
            {
                var unit = priority.Object as WoWUnit;
                if (unit != null)
                {
                    if (unit.Entry == ShadowsofAngerId)
                        priority.Score += 1000;
                }
            }
        }

        #endregion

        private const uint CryptGuardianFuryId = 61783;
        private const uint AbominationOfAngerId = 61707;
        private const int DeathforceId = 120215;
        private const int BladestormId = 128969;
        private const uint ShadowsofAngerId = 62009;

        private const uint JinIronfistId = 61814;

        private static LocalPlayer Me
        {
            get { return StyxWoW.Me; }
        }

        private readonly WoWPoint[] _trapBlackspots = new[] {new WoWPoint(593.493, 2323.363, 67.38953)};

        [EncounterHandler(0)]
        public Composite RootEncounter()
        {
            var stageTwoLoc = new WoWPoint(698.6362, 2467.242, 73.90067);
            var stageThreeLoc = new WoWPoint(640.7203, 2354.263, 63.37622);
            const uint lightningTrapId = 211842;
            const uint fireTrapId = 211841;
            const uint stasisTrapId = 211709;
            const uint statisTrap2Id = 211843;
            const uint activationTrapId = 211995;

            var traps = new[] {fireTrapId, lightningTrapId, stasisTrapId, activationTrapId, statisTrap2Id};

            AddAvoidObject(
                ctx => true,
                4,
                u => u is WoWGameObject && traps.Contains(u.Entry) && u.ZDiff < 10 && u.Distance2D < 10 && !_trapBlackspots.Any(l => l.DistanceSqr(u.Location) < 9));

            return
                new PrioritySelector(
                    new Decorator(
                        ctx => ScriptHelpers.CurrentScenarioInfo.CurrentStageNumber > 1 && ScriptHelpers.IsBossAlive("Jin Ironfist"),
                        new Action(ctx => ScriptHelpers.MarkBossAsDead("Jin Ironfist"))),
                    new Decorator(ctx => ScriptHelpers.CurrentScenarioInfo.CurrentStageNumber == 2, ScriptHelpers.CreateClearArea(() => stageTwoLoc, 50))

                    //new Decorator(ctx => ScriptHelpers.CurrentScenarioInfo.CurrentStageNumber == 3,
                    //new Action(ctx => ScriptHelpers.MoveTankTo(stageThreeLoc)))
                    );
        }

        [EncounterHandler(61814, "Jin Ironfist")]
        public Composite JinIronfistEncounter()
        {
            WoWUnit boss = null;
            return new PrioritySelector(ctx => boss = ctx as WoWUnit, ScriptHelpers.CreateDispellEnemy("Enrage", ScriptHelpers.EnemyDispellType.Enrage, () => boss));
        }

        [EncounterHandler(61766, "Crypt Guardian")]
        [EncounterHandler(61783, "Crypt Guardian")]
        public Composite CryptGuardianEncounter()
        {
            const int guardianStrikeId = 119843;
            WoWUnit unit = null;

            AddAvoidObject(ctx => true, 12, u => u.Entry == CryptGuardianFuryId && (u.ToUnit().CastingSpellId == BladestormId || u.ToUnit().HasAura(BladestormId)));

            return new PrioritySelector(
                ctx => unit = ctx as WoWUnit,
                ScriptHelpers.GetBehindUnit(ctx => unit.CastingSpellId == guardianStrikeId && unit.IsSafelyFacing(Me) && unit.Distance <= 9, () => unit));
        }

        [ObjectHandler(213290, "Treasure Urn", ObjectRange = 30)]
        public Composite TreasureUrnHandler()
        {
            WoWGameObject urn = null;
            return new PrioritySelector(
                ctx => urn = ctx as WoWGameObject, new Decorator(ctx => Targeting.Instance.IsEmpty(), ScriptHelpers.CreateInteractWithObject(() => urn)));
        }

        [EncounterHandler(61707, "Abomination of Anger")]
        public Composite AbominationofAngerEncounter()
        {
            WoWUnit boss = null;
            const uint cloudOfAngerId = 62055;
            const int breathOfHate = 120929;

            AddAvoidObject(ctx => true, 6, cloudOfAngerId);
            AddAvoidObject(ctx => true, 18, u => u.Entry == AbominationOfAngerId && u.ToUnit().ChanneledCastingSpellId == DeathforceId);

            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                ScriptHelpers.CreateAvoidUnitAnglesBehavior(
                    ctx => boss.Distance < 15 && boss.ChanneledCastingSpellId == breathOfHate && boss.CurrentTargetGuid != Me.Guid,
                    () => boss,
                    new ScriptHelpers.AngleSpan(0, 150)));
        }
    }

    #endregion

    #region Heroic Difficulty

    public class CryptOfForgottenKingsHeroic : CryptOfForgottenKings
    {
        #region Overrides of Dungeon

        public override uint DungeonId
        {
            get { return 648; }
        }

        #endregion
    }

    #endregion

}